/*
 * TrackableInterceptor.java
 * Copyright 2021 Qunhe Tech, all rights reserved.
 * Qunhe PROPRIETARY/CONFIDENTIAL, any form of usage is subject to approval.
 */

package cn.org.itool.web.interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.ArrayList;
import java.util.List;

/**
 * 说明拦截器记录了当前请求中的调用顺序，可判断是否有上级拦截器存在
 *
 * 本方法假设所有拦截器只有一个实例
 */
public abstract class TrackableInterceptor implements HandlerInterceptor {

    protected static final String THE_INTERCEPTORS = "__THE_INTERCEPTORS";

    @Override
    public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        getInterceptorClassList(request).add(getClass());
        return doPreHandle(request, response, handler);
    }

    /**
     * 获取拦截器记录链
     * @param request
     * @return
     */
    private List<Class<? extends HandlerInterceptor>> getInterceptorClassList(
            HttpServletRequest request) {
        Object attribute = request.getAttribute(THE_INTERCEPTORS);
        if (attribute instanceof List) {
            return (List<Class<? extends HandlerInterceptor>>) attribute;
        } else {
            List<Class<? extends HandlerInterceptor>> interceptors = new ArrayList<>();
            request.setAttribute(THE_INTERCEPTORS, interceptors);
            return interceptors;
        }
    }

    /**
     * 判断是否在指定拦截器后
     * @param interceptorClass
     * @return
     */
    protected boolean isAfterInterceptor(
            HttpServletRequest request, Class<? extends HandlerInterceptor> interceptorClass) {
        List<Class<? extends HandlerInterceptor>> interceptorClassList = getInterceptorClassList(request);
        int posTarget = interceptorClassList.indexOf(interceptorClass);
        int posSelf = interceptorClassList.indexOf(getClass());

        if (posTarget < 0) {
            return false;
        } else if (posSelf < 0) {
            return true;
        } else {
            return posTarget < posSelf;
        }
    }

    /**
     * 实现实际逻辑
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    protected abstract boolean doPreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
